﻿///////////////////////////////////////////////////////////////////////////////
//
//  This file is part of MathLib.NET.
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//  
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//  
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library;  If not, see 
//  <http://www.gnu.org/licenses/>.
//
///////////////////////////////////////////////////////////////////////////////

using ILNumerics;
using System;
using System.Reflection;

namespace MathLib
{
    /// <summary>
    ///  Signal processing - Linear Systems functions
    /// </summary>
    public partial class MLMath
    {
        //
        // --- Hanning window ---
        //

        /// <summary>
        /// Hanning window
        /// </summary>
        /// <param name="length">The window length</param>
        /// <returns>Symmetric Hann window of length points in column vector format</returns>
        public static ILArray<double> hann(double length)
        {
            try
            {
                int l;

                checked
                {
                    l = (int)(length + 0.5);
                }

                return hann(l);
            }
            catch (MathException ex)
            {
                throw ex;
            }
            catch (OverflowException)
            {
                throw new MathException("Method '" + MethodBase.GetCurrentMethod().Name + "()' parameter 'length' overflow, 'length' must be in the range 0 to " + int.MaxValue.ToString() + ".");
            }
            catch (Exception ex)
            {
                throw new MathException("Method '" + MethodBase.GetCurrentMethod().Name + "()' threw " + ex.GetType().ToString() + " - " + ex.Message, ex);
            }
        }

        /// <summary>
        /// Hanning window
        /// </summary>
        /// <param name="length">The window length</param>
        /// <returns>Symmetric Hann window of length points in column vector format</returns>
        public static ILArray<double> hann(float length)
        {
            try
            {
                int l;

                checked
                {
                    l = (int)(length + 0.5f);
                }

                return hann(l);
            }
            catch (MathException ex)
            {
                throw ex;
            }
            catch (OverflowException)
            {
                throw new MathException("Method '" + MethodBase.GetCurrentMethod().Name + "()' parameter 'length' overflow, 'length' must be in the range 0 to " + int.MaxValue.ToString() + ".");
            }
            catch (Exception ex)
            {
                throw new MathException("Method '" + MethodBase.GetCurrentMethod().Name + "()' threw " + ex.GetType().ToString() + " - " + ex.Message, ex);
            }
        }
 
        /// <summary>
        /// Hanning window
        /// </summary>
        /// <param name="length">The window length</param>
        /// <returns>Symmetric Hann window of length points in column vector format</returns>
        public static ILArray<double> hann(long length)
        {
            try
            {
                int l;

                checked
                {
                    l = (int)length;
                }

                return hann(l);
            }
            catch (MathException ex)
            {
                throw ex;
            }
            catch (OverflowException)
            {
                throw new MathException("Method '" + MethodBase.GetCurrentMethod().Name + "()' parameter 'length' overflow, 'length' must be in the range 0 to " + int.MaxValue.ToString() + ".");
            }
            catch (Exception ex)
            {
                throw new MathException("Method '" + MethodBase.GetCurrentMethod().Name + "()' threw " + ex.GetType().ToString() + " - " + ex.Message, ex);
            }
        } 

        /// <summary>
        /// Hanning window
        /// </summary>
        /// <param name="length">The window length</param>
        /// <returns>Symmetric Hann window of length points in column vector format</returns>
        public static ILArray<double> hann(ulong length)
        {
            try
            {
                int l;

                checked
                {
                    l = (int)length;
                }

                return hann(l);
            }
            catch (MathException ex)
            {
                throw ex;
            }
            catch (OverflowException)
            {
                throw new MathException("Method '" + MethodBase.GetCurrentMethod().Name + "()' parameter 'length' overflow, 'length' must be in the range 0 to " + int.MaxValue.ToString() + ".");
            }
            catch (Exception ex)
            {
                throw new MathException("Method '" + MethodBase.GetCurrentMethod().Name + "()' threw " + ex.GetType().ToString() + " - " + ex.Message, ex);
            }
        } 

        /// <summary>
        /// Hanning window
        /// </summary>
        /// <param name="length">The window length</param>
        /// <returns>Symmetric Hann window of length points in column vector format</returns>
        public static ILArray<double> hann(int length)
        {
            if (length <= 0)
            {
                throw new MathException("Method '" + MethodBase.GetCurrentMethod().Name + "()' parameter 'length' must be greater than 0.");
            }

            ILArray<double> coefficients = new ILArray<double>(new int[] { length, 1 });
            int count = length - 1;

            for (int i = 0; i < count; i++)
            {
                coefficients.InternalArray4Experts[i] = 0.5 * (1.0 - Math.Cos((2.0 * pi) * ((double)i / (double)count)));
            }

            return coefficients;
        }

        /// <summary>
        /// Hanning window
        /// </summary>
        /// <param name="length">The window length</param>
        /// <returns>Symmetric Hann window of length points in column vector format</returns>
        public static ILArray<double> hann(uint length)
        {
            try
            {
                int l;

                checked
                {
                    l = (int)length;
                }

                return hann(l);
            }
            catch (MathException ex)
            {
                throw ex;
            }
            catch (OverflowException)
            {
                throw new MathException("Method '" + MethodBase.GetCurrentMethod().Name + "()' parameter 'length' overflow, 'length' must be in the range 0 to " + int.MaxValue.ToString() + ".");
            }
            catch (Exception ex)
            {
                throw new MathException("Method '" + MethodBase.GetCurrentMethod().Name + "()' threw " + ex.GetType().ToString() + " - " + ex.Message, ex);
            }
        } 

        /// <summary>
        /// Hanning window
        /// </summary>
        /// <param name="length">The window length</param>
        /// <returns>Symmetric Hann window of length points in column vector format</returns>
        public static ILArray<double> hann(short length)
        {
            try
            {
                return hann((int)length);
            }
            catch (MathException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                throw new MathException("Method '" + MethodBase.GetCurrentMethod().Name + "()' threw " + ex.GetType().ToString() + " - " + ex.Message, ex);
            }
        } 

        /// <summary>
        /// Hanning window
        /// </summary>
        /// <param name="length">The window length</param>
        /// <returns>Symmetric Hann window of length points in column vector format</returns>
        public static ILArray<double> hann(ushort length)
        {
            try
            {
                return hann((int)length);
            }
            catch (MathException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                throw new MathException("Method '" + MethodBase.GetCurrentMethod().Name + "()' threw " + ex.GetType().ToString() + " - " + ex.Message, ex);
            }
        } 

        /// <summary>
        /// Hanning window
        /// </summary>
        /// <param name="length">The window length</param>
        /// <returns>Symmetric Hann window of length points in column vector format</returns>
        public static ILArray<double> hann(char length)
        {
            try
            {
                return hann((int)length);
            }
            catch (MathException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                throw new MathException("Method '" + MethodBase.GetCurrentMethod().Name + "()' threw " + ex.GetType().ToString() + " - " + ex.Message, ex);
            }
        } 

        /// <summary>
        /// Hanning window
        /// </summary>
        /// <param name="length">The window length</param>
        /// <returns>Symmetric Hann window of length points in column vector format</returns>
        public static ILArray<double> hann(byte length)
        {
            try
            {
                return hann((int)length);
            }
            catch (MathException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                throw new MathException("Method '" + MethodBase.GetCurrentMethod().Name + "()' threw " + ex.GetType().ToString() + " - " + ex.Message, ex);
            }
        }        
    }
}
